﻿namespace fleetIt
{
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Diagnostics;
    using System.IO;
    using System.Linq;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Input;
    using System.Windows.Threading;
    using System.Xml;
    using fleetIt.Core;
    using fleetIt.DO;

    /// <summary>
    /// 
    /// </summary>
    public partial class MainUI : Window
    {
        private string _userKey = string.Empty;
        private bool _IsLoggedIn = false;
        private bool _IsConnected = false;
        private BackgroundWorker _BackgroundWorker;
        private delegate void UpdateProgressHandler(int percentage);

        private const string SUCCESS = "success";
        private DispatcherTimer _dispatcherTimer;
        /// <summary>
        /// 
        /// </summary>
        public MainUI()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            this.chkRememberMe.IsChecked = Properties.Settings.Default.RememberMe;
            if (this.chkRememberMe.IsChecked.Value)
            {
                this.txtUserKey.Text = Properties.Settings.Default.UserKey;
            }
            this._BackgroundWorker = new BackgroundWorker();
            this._BackgroundWorker.DoWork += new DoWorkEventHandler(_BackgroundWorker_DoWork);
            this._BackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(_BackgroundWorker_RunWorkerCompleted);

            this._dispatcherTimer = new DispatcherTimer();
            this._dispatcherTimer.Interval = new TimeSpan(0, Properties.Settings.Default.RefreshInterval, 0);
            this._dispatcherTimer.IsEnabled = true;
            this._dispatcherTimer.Tick += new EventHandler(_dispatcherTimer_Tick);
        }

        private void _dispatcherTimer_Tick(object sender, EventArgs e)
        {
            this.RefreshCommand.Command.Execute(null);
        }

        private void UpdateProgressThreaded(int percentage)
        {
            this.prgInfo.Dispatcher.Invoke(new UpdateProgressHandler(this.UpdateProgress), new object[] { percentage });
        }

        private void UpdateProgress(int percentage)
        {
            if (percentage == 100)
            {
                this.prgInfo.Visibility = Visibility.Hidden;
            }
            else
            {
                this.prgInfo.Visibility = Visibility.Visible;
            }
            this.prgInfo.Value = percentage;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _BackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                Fleets fleet = e.Result as Fleets;
                this.lstFleets.DataContext = fleet.fleets;
                this.UpdateProgressThreaded(95);
                this._IsConnected = true;
            }
            else
            {
                this._IsConnected = false;
            }
            this.UpdateProgressThreaded(100);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            e.Result = this.GetAllFleets();
        }

        /// <summary>
        /// 
        /// </summary>
        private void SignIn()
        {
            if (this.chkRememberMe.IsChecked.Value)
            {
                Properties.Settings.Default.UserKey = this.txtUserKey.Text;
                Properties.Settings.Default.RememberMe = true;
                Properties.Settings.Default.Save();
            }
            else
            {
                Properties.Settings.Default.UserKey = string.Empty;
                Properties.Settings.Default.RememberMe = false;
                Properties.Settings.Default.Save();
            }
            this._userKey = this.txtUserKey.Text;
            this._IsLoggedIn = true;
            this.splFleets.Visibility = Visibility.Visible;
            this.splLogin.Visibility = Visibility.Collapsed;
            this._BackgroundWorker.RunWorkerAsync();
            this._dispatcherTimer.Start();
        }

        /// <summary>
        /// 
        /// </summary>
        private void GetAllUsers()
        {
            Dictionary<string, string> parameters = new Dictionary<string, string>(2);
            parameters.Add("appKey", Properties.Settings.Default.ApplicationKey);
            if (Properties.Settings.Default.LastGetFleetDate.Equals(string.Empty))
            {
                Properties.Settings.Default.LastGetFleetDate = DateTime.Now.ToString("yyyy-MM-dd HH:MM:ss");
                Properties.Settings.Default.Save();
            }
            parameters.Add("userKey", this._userKey);
            using (Common common = new Common())
            {
                common.SendRequest(RequestMethod.GET, "http://assyst.inetoffice.in/api/user_fleets",
                     ResponseFormats.xml, parameters);
            }
        }

        /// <summary>
        /// Gets all fleets.
        /// </summary>
        private Fleets GetAllFleets()
        {
            string fileName = string.Empty;
            string AppDataDirectory = string.Empty;

            this.UpdateProgressThreaded(10);

            Properties.Settings.Default.LastGetFleetDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:00");
            Properties.Settings.Default.Save();

            this.UpdateProgressThreaded(15);
            Dictionary<string, string> parameters = new Dictionary<string, string>(1);
            this.UpdateProgressThreaded(20);
            parameters.Add("appKey", Properties.Settings.Default.ApplicationKey);
            this.UpdateProgressThreaded(25);
            string lastFleetDate = Properties.Settings.Default.LastGetFleetDate;
            this.UpdateProgressThreaded(30);
            parameters.Add("sinceDate", lastFleetDate);
            this.UpdateProgressThreaded(35);
            using (Common common = new Common())
            {
                this.UpdateProgressThreaded(65);
                XmlDocument xmlDocument = common.GetResponseXml(common.SendRequest(RequestMethod.GET,
                    "http://assyst.inetoffice.in/api/all_fleets",
                     ResponseFormats.xml, parameters));
                this.UpdateProgressThreaded(75);

                Fleets fleetsNew = common.CreateObject<Fleets>(xmlDocument);
                Fleets fleetsExisting = null;
                Fleets fleetsFinal = null;
                AppDataDirectory = String.Format("{0}/DataCache/", Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData));
                if (!Directory.Exists(AppDataDirectory))
                {
                    Directory.CreateDirectory(AppDataDirectory);
                }
                this.UpdateProgressThreaded(70);
                string currentDate = DateTime.Now.ToShortDateString().Replace("/", "_");
                fileName = Path.Combine(AppDataDirectory, Path.ChangeExtension(currentDate, "cache"));
                if (File.Exists(fileName))
                {
                    fleetsExisting = common.ReadObjectCache(fileName) as Fleets;
                }
                this.UpdateProgressThreaded(75);
                List<Fleet> listOfFleets = null;
                if (fleetsExisting != null)
                {
                    listOfFleets = fleetsExisting.fleets.Concat(fleetsNew.fleets).
                        Distinct(new DistinctFleetComparer()).OrderByDescending(f => f.updated_on).ToList();
                    this.UpdateProgressThreaded(80);
                    fleetsFinal = new Fleets()
                    {
                        fleets = listOfFleets,
                        total = listOfFleets.Count
                    };
                }
                else
                {
                    this.UpdateProgressThreaded(80);
                    fleetsFinal = fleetsNew;
                }
                common.CreateObjectCache(fleetsFinal, fileName);
                return fleetsFinal;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Window_Closing(object sender, CancelEventArgs e)
        {
            if (MessageBox.Show(string.Format("Are you sure you want to exit {0}?", this.Title), this.Title, MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.No)
            {
                e.Cancel = true;
            }
            else
            {
                if (this._dispatcherTimer != null)
                {
                    this._dispatcherTimer.Stop();
                    this._dispatcherTimer = null;
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void urlClick_Click(object sender, RoutedEventArgs e)
        {
            this.StartUrl("http://www.dotnetthoughts.net");
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Window_StateChanged(object sender, EventArgs e)
        {
            //if (this.WindowState == WindowState.Minimized)
            //{
            //    this.fleetItNotificationIcon.Visibility = Visibility.Visible;
            //    this.Visibility = Visibility.Collapsed;
            //}
            //else
            //{
            //    this.fleetItNotificationIcon.Visibility = Visibility.Hidden;
            //    this.Visibility = Visibility.Visible;
            //}
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void mniRestore_Click(object sender, RoutedEventArgs e)
        {
            this.Visibility = Visibility.Visible;
            this.WindowState = WindowState.Normal;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="format"></param>
        private void TextFormatting(string format)
        {
            this.txtFleet.SelectedText = string.Format(format, this.txtFleet.SelectedText);
        }

        /// <summary>
        /// 
        /// </summary>
        private void NotImplemented()
        {
            MessageBox.Show("Not implemented", this.Title, MessageBoxButton.OK, MessageBoxImage.Information);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cmbSmiley_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
        {
            if (this.cmbSmiley.SelectedIndex != 0)
            {
                this.txtFleet.SelectedText = (this.cmbSmiley.SelectedItem as ComboBoxItem).Tag.ToString();
                this.cmbSmiley.SelectedIndex = 0;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="url"></param>
        private void StartUrl(string url)
        {
            Process.Start(url);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void RefreshCommand_CanExecute(object sender, System.Windows.Input.CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = this._IsLoggedIn && !this._BackgroundWorker.IsBusy;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void RefreshCommand_Executed(object sender, System.Windows.Input.ExecutedRoutedEventArgs e)
        {
            if (!this._BackgroundWorker.IsBusy)
            {
                this.lstFleets.DataContext = null;
                this._BackgroundWorker.RunWorkerAsync();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ExitCommand_CanExecute(object sender, System.Windows.Input.CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ExitCommand_Executed(object sender, System.Windows.Input.ExecutedRoutedEventArgs e)
        {
            this.Close();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void AboutCommand_CanExecute(object sender, System.Windows.Input.CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void AboutCommand_Executed(object sender, System.Windows.Input.ExecutedRoutedEventArgs e)
        {
            string about = "{0} v0.06 Alpha\nA WPF Client for TeamSpace\n\nCopyright © 2010 {0} developers.\nAll rights reserverd.";
            about += "\n\nPowered by dotnetthoughts labs";
            MessageBox.Show(string.Format(about, this.Title), this.Title, MessageBoxButton.OK, MessageBoxImage.Information);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void UnderlineCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = this.txtFleet != null && this.txtFleet.SelectionLength > 0;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void UnderlineCommand_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            this.TextFormatting("<u>{0}</u>");
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BoldCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = this.txtFleet != null && this.txtFleet.SelectionLength > 0;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BoldCommand_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            this.TextFormatting("<b>{0}</b>");
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ItalicCommand_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            this.TextFormatting("<i>{0}</i>");
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ItalicCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = this.txtFleet != null && this.txtFleet.SelectionLength > 0;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void StrikeThroughCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = this.txtFleet != null && this.txtFleet.SelectionLength > 0;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void StrikeThroughCommand_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            this.TextFormatting("<del>{0}</del>");
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void InsertLinkCommand_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            LinkUI linkUi = new LinkUI();
            linkUi.Owner = this;
            if (linkUi.ShowDialog().Value)
            {
                this.txtFleet.SelectedText = linkUi.Url;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void InsertLinkCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = this._IsConnected;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void PasteCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = Clipboard.ContainsText();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void PasteCommand_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            this.txtFleet.SelectedText = Clipboard.GetText();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void SignInCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = this.txtUserKey.Text.Length == 40;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void SignInCommand_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            this.SignIn();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FleetMyStatusCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = this._IsConnected && this.txtFleet.Text.Length > 0;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FleetMyStatusCommand_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            this.cmdFleetMyStatus.IsEnabled = false;
            this.UpdateProgressThreaded(10);
            using (Common common = new Common())
            {
                this.UpdateProgressThreaded(20);
                Dictionary<string, string> parameters = new Dictionary<string, string>();
                parameters.Add("appKey", Properties.Settings.Default.ApplicationKey);
                this.UpdateProgressThreaded(25);
                parameters.Add("userKey", this._userKey);
                this.UpdateProgressThreaded(30);
                parameters.Add("fleet", this.txtFleet.Text);
                this.UpdateProgressThreaded(35);
                XmlDocument xmlDocument = common.GetResponseXml(common.SendRequest(RequestMethod.POST, "http://assyst.inetoffice.in/api/post_fleet", ResponseFormats.xml,
                    parameters));
                this.UpdateProgressThreaded(85);
                if (xmlDocument.SelectSingleNode("//status").InnerText.Equals(SUCCESS))
                {
                    this.txtFleet.Text = string.Empty;
                    this.txtFleet.Focus();
                }
            }
            this.UpdateProgressThreaded(100);
            //Refreshing the Items.
            this.RefreshCommand.Command.Execute(null);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ProfileCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = this._IsConnected;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ProfileCommand_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            string user = (e.Parameter as XmlElement).InnerText;
            string profileurl = string.Format("http://assyst.inetoffice.in/profiles/{0}", user);
            this.StartUrl(profileurl);
        }

        private void ReplyFleetCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = this.lstFleets != null && this.lstFleets.SelectedItem != null;
        }

        private void ReplyFleetCommand_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            this.NotImplemented();
        }

        private void MarkAsFavCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = this.lstFleets != null && this.lstFleets.SelectedItem != null;
        }

        private void MarkAsFavCommand_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            this.NotImplemented();
        }

        private void DeleteCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = this.lstFleets != null && this.lstFleets.SelectedItem != null;
        }

        private void DeleteCommand_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            //fleetID 
            //http://assyst.inetoffice.in/api/delete_fleet
            this.NotImplemented();
        }

        private void SettingsCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = this._IsLoggedIn;
        }

        private void SettingsCommand_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            SettingsUI settingsUI = new SettingsUI();
            settingsUI.Owner = this;
            settingsUI.ShowDialog();
        }

        private void VersionCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private void VersionCommand_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            string version = string.Format("{0} - Version History", this.Title);
            version += "\n\nv0.06 Alpha - 8th June 2010\nCaching implemented for fleets";
            version += "\nBug fixes\nImplemented Settings.";
            version += "\n\nv0.05 Alpha - 8th June 2010\nResolved logical issue with Getting fleets";
            version += "\nUser Icons implemented(Now supported by Teamspace API).";
            version += "\n\nv0.04 Alpha - 7th June 2010\nPosting fleet feature added.";
            version += "\nAuto Refresh implemented.";
            version += "\n\nv0.03 Alpha - 6th June 2010\nSupport added URL Shortening(bit.ly)";
            version += "\nAdded to codeplex. fleetIt.codeplex.com";
            version += "\nSupport added more URL Shortening sevices(tiny.cc, tinyurl.com)";
            version += "\n\nv0.02 Alpha - 5th June 2010\nSupport added for reading all fleets, Editor and UI";
            version += "\n\nv0.01 Alpha - 4th June 2010\nSignIn functionality, Core Libraries";
            MessageBox.Show(version, this.Title, MessageBoxButton.OK, MessageBoxImage.Information);
        }
    }
}